package com.lxl.securitypermission.config.custom;

import com.lxl.securitypermission.pojo.RolePermission;
import com.lxl.securitypermission.service.RoleService;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

@Slf4j
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {

  @Autowired
  private RoleService roleService;
  private AntPathMatcher matcher = new AntPathMatcher();

  @Override
  public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
      throws AccessDeniedException, InsufficientAuthenticationException {
    //可在此处return null 表示白名单 ，添加缓存名单
    final HttpServletRequest request = ((FilterInvocation) object).getRequest();
    boolean allowAccess = true;
    String url = request.getRequestURI();
    ////可以使用redis的 list 存储列表
    List<RolePermission> rolePermissions = roleService.getAllRolePermission();
    for (RolePermission rp : rolePermissions) {
      if (matcher.match(rp.getPattern(), url)) {
        //判断是否存在角色
        for (GrantedAuthority authority : authentication.getAuthorities()) {
          if (authority.getAuthority().equals(rp.getRoleName())) {
            //存在角色时，判断是否有读写权限
            String red = request.getMethod().equals("GET") ? "R" : "W";
            if (rp.getAction().indexOf(red) != -1) {
              //存在读写权限，允许访问
              return;
            }
          }
        }
        allowAccess = false;
      }
    }
    //根据上面的判断，是否可通过
    if (!allowAccess) {
      //记录日志
      log.warn("无权限执行当前操作:{}", authentication.getPrincipal());
      throw new AccessDeniedException("无权限执行当前操作！");
    }

    //return 表示允许通过
    return;
  }

  @Override
  public boolean supports(ConfigAttribute attribute) {
    return false;
  }

  @Override
  public boolean supports(Class<?> clazz) {
    return false;
  }

  public static void main(String[] args) {
    List<Collection> a = new ArrayList<>();

  }
}
